function processFile(blob, fileName) { var tolRaw = parseInt(($('input[name="0"]').val() || '32'), 10); if (!isFinite(tolRaw)) tolRaw = 32; var tolerance = Math.max(0, Math.min(150, tolRaw)); var img = new Image(); img.onload = function() { var w = img.naturalWidth, h = img.naturalHeight; if (!w || !h) { alert('Could not decode this image.'); return; } var maxDim = 2400; var scale = Math.min(1, maxDim / Math.max(w, h)); var cw = Math.max(1, Math.round(w * scale)); var ch = Math.max(1, Math.round(h * scale)); var c = document.createElement('canvas'); c.width = cw; c.height = ch; var ctx = c.getContext('2d'); ctx.drawImage(img, 0, 0, cw, ch); var imgData; try { imgData = ctx.getImageData(0, 0, cw, ch); } catch (e) { alert('Could not read pixels (browser security). Try a smaller image.'); return; } var data = imgData.data; // Sample the four corners + edge midpoints for the background palette. var samples = [ [0, 0], [cw - 1, 0], [0, ch - 1], [cw - 1, ch - 1], [Math.floor(cw / 2), 0], [Math.floor(cw / 2), ch - 1], [0, Math.floor(ch / 2)], [cw - 1, Math.floor(ch / 2)] ]; var palette = samples.map(function(p){ var idx = (p[1] * cw + p[0]) * 4; return [data[idx], data[idx + 1], data[idx + 2]]; }); // Flood-fill from each sample point, marking connected pixels within tolerance as background. var visited = new Uint8Array(cw * ch); var stack = []; var tolSq = tolerance * tolerance * 3; function similar(r, g, b, base) { var dr = r - base[0], dg = g - base[1], db = b - base[2]; return (dr * dr + dg * dg + db * db) <= tolSq; } for (var s = 0; s < samples.length; s++) { var sp = samples[s]; var base = palette[s]; stack.push(sp[0], sp[1]); while (stack.length) { var py = stack.pop(); var px = stack.pop(); if (px < 0 || py < 0 || px >= cw || py >= ch) continue; var vidx = py * cw + px; if (visited[vidx]) continue; var didx = vidx * 4; if (!similar(data[didx], data[didx + 1], data[didx + 2], base)) continue; visited[vidx] = 1; stack.push(px + 1, py, px - 1, py, px, py + 1, px, py - 1); } } // Soften the mask edge by feathering: pixels next to a non-bg pixel keep some alpha. for (var y = 0; y < ch; y++) { for (var x = 0; x < cw; x++) { var vidx = y * cw + x; if (!visited[vidx]) continue; var edge = false; if (x > 0 && !visited[vidx - 1]) edge = true; else if (x < cw - 1 && !visited[vidx + 1]) edge = true; else if (y > 0 && !visited[vidx - cw]) edge = true; else if (y < ch - 1 && !visited[vidx + cw]) edge = true; var didx = vidx * 4; data[didx + 3] = edge ? 80 : 0; } } ctx.putImageData(imgData, 0, 0); c.toBlob(function(outBlob) { if (!outBlob) { alert('Could not generate the transparent PNG.'); return; } var base = (fileName || 'image').replace(/\.[^.]+$/, ''); add_file_output(URL.createObjectURL(outBlob), base + '-nobg.png'); }, 'image/png'); }; img.onerror = function(){ alert('Could not read this image file.'); }; img.src = URL.createObjectURL(blob); } var _loadedScripts = {}; function loadScriptPromise(url) { if (_loadedScripts[url]) return _loadedScripts[url]; _loadedScripts[url] = new Promise(function (resolve, reject) { var s = document.createElement('script'); s.src = url; s.onload = resolve; s.onerror = reject; document.head.appendChild(s); }); return _loadedScripts[url]; } function replaceAll(find, replace, str) { return str.replace(new RegExp(find, 'g'), replace); } function beautify(str) { var result = ''; var length = str.length; var i = 0; var braceCountLeft = 0; var braceCountRight = 0; var withinQuotes = false; while (i < length) { var c = str[i]; if (c == '"' && (i == 0 || c[i - 1] != '\\')) { // non-escaped quotes withinQuotes = !withinQuotes; } if (!withinQuotes && (c == '}' || c == '{' || c == ',')) { console.log('Start####' + result); // look back and remove carriage returns and whitespace that are already there var resultIndex = result.length - 1; while (resultIndex >= 0 && (result[resultIndex] == ' ' || result[resultIndex] == '\r' || result[resultIndex] == '\n' || result[resultIndex] == '\t')) { resultIndex = resultIndex - 1; result = result.substr(0, resultIndex + 1); console.log('char ' + result[resultIndex] + '-----' + result + 'zzz ' + result.length + ' ' + resultIndex); } if (c == '{') { braceCountLeft++; result += c + '\r' + GetTabs(braceCountLeft - braceCountRight); } else if (c == '}') { braceCountRight++; // precede with carriage return result += '\r' + GetTabs(braceCountLeft - braceCountRight) + c; } else if (c == ',') { result += c + '\r' + GetTabs(braceCountLeft - braceCountRight); } var nextChar = ''; // advance through whitespace and remove carriage returns that are already there while (i < length && (str[i + 1] == ' ' || str[i + 1] == '\r' || str[i + 1] == '\n' || str[i + 1] == '\t')) { i++; } } else { result += str[i]; } i++; } return result; } function GetTabs(count) { var result = ''; for (var i = 0; i < count; i++) { result += ' '; } return result; }